package com.cskaoyan.javase.reflect._2clazz;

/**
 * 获取某个类的运行时类对象,也就是java.lang.Class对象
 * 因为类加载只有一次,所有某种类型的Class对象也是唯一的
 *      1.getClass()方法 必须new某个类的对象,因为它是成员方法
 *          因为要创建对象,局限性很大,几乎不用这种方式获取Class对象
 *      2.Java每一个数据类型,都会自带一个隐含的静态属性
 *          ".class"
 *          通过这种方式就可以获取该类型的Class对象
 *          注:基本数据类型也有这个静态属性,目的是为了配合后续反射过程中
 *          描述形参数据类型,返回值数据类型使用的
 *          这种方式也很少使用,基本上只作为方法传参时使用
 *          (后续API还会再演示)
 *      3.(最常用,最推荐)
 *      Class.forName(全限定类名);
 *      不管用什么方式获取Class对象,Class对象都是唯一的,只有一个
 *
 * Class对象是类加载器在类加载某个类的加载阶段,在堆上创建的对象,上述三种方式都只是获取Class对象,不是创建Class对象
 *
 * 方式二和方式三的区别:
 *      1.方式二和方式三都会触发类的类加载
 *          方式二触发的类加载不是一次完整的类加载, 类加载的初始化不会执行
 *          方式三触发的类加载是一次完整的类加载,该类的类加载会进行初始化操作
 *      2.方式三因为它直接用一个全限定类名字符串指定一个类，更加灵活。尤其是在配合配置文件使用的时候，它的优越性秒杀其它方式。
 *
 * @since 09:57
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) throws ClassNotFoundException {
        /*Student s = new Student();
        // System.out.println(s.getClass());
        Class stuClazz = s.getClass();
        Class stuClazz2 = Student.class;

        // true
        System.out.println(stuClazz == stuClazz2);

        System.out.println(int.class);
        System.out.println(Integer.class);
        System.out.println(int.class == Integer.class);

        // 方式三
        Class<?> stuClazz3 = Class.forName("com.cskaoyan.javase.reflect._2clazz.Student");

        // true
        System.out.println(stuClazz3 == stuClazz2);
        System.out.println(stuClazz3 == stuClazz);*/

        // System.out.println(Student.class);
        Class<?> stuClazz3 = Class.forName("com.cskaoyan.javase.reflect._2clazz.Student");
    }
}

class Student {
    static {
        System.out.println("Student初始化执行了,类加载的最后一个阶段执行了!");
    }
}